
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <U8g2lib.h>

// 定义 Wi-Fi 网络信息
const char *ssid = "xxx";
const char *pwd = "s7qrf2nz";

// 心知天气 API 相关配置
const String xz_api_key = "SNCzJwtP7sPewgiKq";                                  // 心知 API 秘钥
const String city = "fujianFuzhou";                                             // 城市名称
const String weather_api_url = "https://api.seniverse.com/v3/weather/now.json"; // 天气 API URL

// 创建一个动态 JSON 文档，大小为 1024 字节，使用推荐方式
const size_t capacity = JSON_OBJECT_SIZE(3) + 1024;
DynamicJsonDocument doc(capacity);

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 9, /* data=*/ 8, /* reset=*/ U8X8_PIN_NONE);

// 定义屏幕起点的偏移量
#define SCREEN_OFFSET_X 30
#define SCREEN_OFFSET_Y 14

// 创建宏来自动补偿屏幕起点偏移，分别处理X和Y坐标
#define COMPENSATE_X(x) ((x) + SCREEN_OFFSET_X)
#define COMPENSATE_Y(y) ((y) + SCREEN_OFFSET_Y)

// WiFi 连接函数
void connectToWiFi()
{
    Serial.print("正在连接到 Wi-Fi: ");
    Serial.println(ssid);
    WiFi.begin(ssid, pwd);

    // 等待 Wi-Fi 连接成功
    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(500);
    }

    Serial.println("\n连接成功！");
    Serial.print("本地 IP 地址: ");
    Serial.println(WiFi.localIP());
}

// 获取天气信息的函数
int getWeather()
{
    // 构建完整的 API 请求 URL
    String url = weather_api_url + "?key=" + xz_api_key + "&location=" + city + "&language=zh-Hans&unit=c";

    // 初始化 HTTP 客户端
    HTTPClient http;
    http.begin(url);

    // 发送 GET 请求
    int httpResponseCode = http.GET();

    // 检查 HTTP 响应码
    if (httpResponseCode != HTTP_CODE_OK)
    {
        Serial.printf("GET 请求失败，HTTP 状态码: %d, 错误信息: %s\n", httpResponseCode, http.errorToString(httpResponseCode).c_str());
        http.end(); // 关闭 HTTP 连接
        return -1;
    }

    // 获取响应内容
    String response = http.getString();
    Serial.printf("API 响应: [%s]\n", response.c_str());

    // 解析 JSON 响应
    DeserializationError error = deserializeJson(doc, response);
    if (error)
    {
        Serial.printf("JSON 解析失败: %s\n", error.c_str());
        http.end(); // 关闭 HTTP 连接
        return -1;
    }

    // 提取并打印天气信息
    if (doc["results"].size() > 0)
    {
        JsonObject result = doc["results"][0];

        // 提取位置信息
        JsonObject location = result["location"];
        const char *path = location["path"];
        Serial.printf("地理位置: %s\n", path);

        // 提取当前天气信息
        JsonObject now = result["now"];
        const char *text = now["text"];
        const char *temperature = now["temperature"];
        Serial.printf("天气状况: %s\n", text);
        Serial.printf("当前温度: %s°C\n", temperature);

        // 提取最后更新时间
        const char *lastUpdate = result["last_update"];
        Serial.printf("最后更新时间: %s\n", lastUpdate);

        // do-while循环确保页面内容被正确绘制
        // nextPage()返回false时表示所有页面都已绘制完毕
        do
        {
            // 设置字体为u8g2_font_ncenB10_tr，这是一种等宽的粗体10点字体
            u8g2.setFont(u8g2_font_ncenB10_tr);

            // 在屏幕上指定位置绘制字符串
            u8g2.drawStr(COMPENSATE_X(0), COMPENSATE_Y(0) + 10, "Arduino");
            u8g2.drawStr(COMPENSATE_X(0), COMPENSATE_Y(0) + 20, "--------------------");
            u8g2.drawStr(COMPENSATE_X(0), COMPENSATE_Y(0) + 30, temperature);

        } while (u8g2.nextPage()); // 继续绘制下一页，直到所有页都绘制完成
    }
    else
    {
        Serial.println("API 响应中没有找到有效的天气数据");
        return -1;
    }

    // 关闭 HTTP 连接
    http.end();
    return 0;
}

void setup()
{
    // 初始化串口通信
    Serial.begin(115200);
    delay(1000); // 等待串口初始化完成

    // 连接到 Wi-Fi
    connectToWiFi();

    // 初始化 OLED，移除 U8X8_CLOCKSOURCE_NONE 参数
    if (!u8g2.begin()) {
        Serial.println("OLED initialization failed!");
        while (1); // 停止程序，方便排查问题
    }
    u8g2.setFont(u8g2_font_ncenB08_tr);
    // // 测试显示
    u8g2.firstPage();
    // do {
    //     u8g2.setDrawColor(1);
    //     u8g2.drawStr(0, 10, "OLED Test");
    // } while (u8g2.nextPage());
    // delay(3000); // 显示 3 秒测试信息
    // u8g2.clearBuffer();
}

void loop()
{
    // 每隔 60 秒获取一次天气信息
    if (getWeather() == 0)
    {
        Serial.println("天气信息获取成功！");
    }
    else
    {
        Serial.println("天气信息获取失败！");
    }

    // 等待 60 秒后再次获取天气信息
    delay(60000);
}